pub mod client {
    use crate::models::{Response, SharedData};
    use actix_web::{HttpRequest, HttpResponse, get, post, web};

    #[get("/status/{uid}")]
    pub async fn status(uid: web::Path<u32>, data: web::Data<SharedData>) -> HttpResponse {
        match data.lock().unwrap().who(*uid) {
            Some(address) => HttpResponse::Ok().json(Response::new(0, "occupied", Some(address))),
            None => HttpResponse::Ok().json(Response::<()>::new(2, "vacant", None)),
        }
    }

    #[post("/launch/{uid}")]
    pub async fn launch(
        req: HttpRequest,
        uid: web::Path<u32>,
        data: web::Data<SharedData>,
    ) -> HttpResponse {
        let address = req.peer_addr().unwrap().ip();
        let result = data.lock().unwrap().occupy(*uid, address);
        match result {
            Ok(_) => HttpResponse::Ok().json(Response::<()>::new(1, "launched", None)),
            Err(err) => {
                log::info!("occupied by {:?}, status: {:?}", address, err);
                HttpResponse::Ok().json(Response::new(0, "occupied", Some(address)))
            }
        }
    }

    #[post("/stop/{uid}")]
    pub async fn stop(uid: web::Path<u32>, data: web::Data<SharedData>) -> HttpResponse {
        let _ = data.lock().unwrap().into_vacant(*uid).map_err(|err| {
            log::info!("error when stop:{:?}", err);
        });

        HttpResponse::Ok().json(Response::<()>::new(2, "stoped", None))
    }
}

pub mod device {

    use crate::models::{DevResponse, SharedData};
    use actix_web::{HttpResponse, get, web};
    use log::error;

    #[get("/register/{uid}")]
    pub async fn register(uid: web::Path<u32>, data: web::Data<SharedData>) -> HttpResponse {
        match data.lock().unwrap().register(*uid) {
            Ok(_) => HttpResponse::Ok().json(DevResponse::success()),
            Err(err) => {
                error!("register: {:?}", err);
                return HttpResponse::Ok().json(DevResponse::failure());
            }
        }
    }

    #[get("/status/{uid}")]
    pub async fn status(uid: web::Path<u32>, data: web::Data<SharedData>) -> HttpResponse {
        log::info!("Status: {:?}", uid);

        // let mut occupied = false;
        let is_occupied = match data.lock() {
            Ok(guard) => guard.is_occupied(*uid),
            Err(err) => {
                // occupied = false;
                log::error!("when query status: {:?}", err);
                false
            }
        };

        HttpResponse::Ok().json(if is_occupied {
            DevResponse::success() // has occupied
        } else {
            DevResponse::failure() // ready to used
        })
    }
}
